
#include "../include/mystdafx.h"
#include "../os/os_thread.h"

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// linux

#ifndef WIN32

typedef struct 
{
	pthread_t hThread;
}os_thread_priv_t;

static void* os_thread_proc_linux(void* param)
{
	os_thread_t* th = (os_thread_t*) param;
	th->_pRoutine(th->_pContext);	return NULL;
}

int os_thread_create(os_thread_t* th, os_thread_routine_t routine, void* context)
{
	th->_pContext = context;
	th->_pRoutine = routine;
	th->pPriv = NULL;
	return 0;
}

void os_thread_destroy(os_thread_t* th)
{
	if(th->pPriv)
	{
		os_thread_priv_t* priv = (os_thread_priv_t*) th->pPriv;
		delete priv;
		th->pPriv = NULL;
	}
}

unsigned long int os_thread_run(os_thread_t* th)
{
	unsigned long int thread_id = -1 ;

	// ����˽�нṹ
	os_thread_priv_t* priv = new os_thread_priv_t;
	if(!priv) 
		return -1;

	th->pPriv = priv;

	// �����߳�

	if(pthread_create(&priv->hThread, NULL, os_thread_proc_linux, th) < 0)
	{
		delete priv;
		th->pPriv = NULL;
		return -1;
	}

	thread_id = priv->hThread;

	return thread_id;
}

void os_thread_stop(os_thread_t* th)
{
	if(th->pPriv)
	{
		os_thread_priv_t* priv = (os_thread_priv_t*)th->pPriv;
		int rc = pthread_join ((pthread_t)priv->hThread, NULL);
	}
}

/////////// global function ////////////
int os_thread_join(os_thread_t* th)
{
	os_thread_priv_t* priv = (os_thread_priv_t*) th->pPriv;
	if(priv)
	{
		pthread_join(priv->hThread, NULL);

		if(th->pPriv)
		{
			// ɾ����Դ
			delete priv;
			th->pPriv = NULL;
		}
	}
	return 0;
}

void os_thread_msleep(int ms)
{
	struct timespec ts;
	ts.tv_sec = ms / 1000;
	ts.tv_nsec = (ms % 1000) * 1000000;
	nanosleep(&ts, NULL);
}

void os_thread_sleep(int s)
{
	sleep(s);
}

unsigned long int os_thread_id()
{
	return (unsigned long int)pthread_self();
}

#endif




//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// windows

#ifdef WIN32

typedef struct 
{
	HANDLE hThread;
}os_thread_priv_t;

static unsigned int WINAPI os_thread_proc_win32(void* param)
{
	os_thread_t* th = (os_thread_t*) param;
	th->_pRoutine(th->_pContext);
	return 0;
}

int os_thread_create(os_thread_t* th, os_thread_routine_t routine, void* context)
{
	th->_pContext = context;
	th->_pRoutine = routine;
	th->pPriv = NULL;
	return 0;
}

void os_thread_destroy(os_thread_t* th)
{
	if(th->pPriv)
	{
		os_thread_priv_t* priv = (os_thread_priv_t*) th->pPriv;
		delete priv;
		th->pPriv = NULL;
	}
}

unsigned long int os_thread_run(os_thread_t* th)
{
	unsigned int thread_id ;

	// ����˽�нṹ
	os_thread_priv_t* priv = new os_thread_priv_t;
	if(!priv) return -1;

	th->pPriv = priv;

	// �����߳�
	priv->hThread = (HANDLE) _beginthreadex(NULL, 0, os_thread_proc_win32, th, 0, &thread_id);
	if(priv->hThread == NULL)
	{
		delete priv;
		th->pPriv = NULL;
		return -1;
	}

	return thread_id;
}

void os_thread_stop(os_thread_t* th)
{
	DWORD rc = WaitForSingleObject (th->pPriv, INFINITE);
	if(th->pPriv)
	{
		//assert (rc != WAIT_FAILED);
		BOOL rc2 = CloseHandle (th->pPriv);
		assert (rc2 != 0);
	}
}

/////////// global function ////////////
int os_thread_join(os_thread_t* th)
{
	os_thread_priv_t* priv = (os_thread_priv_t*) th->pPriv;
	if(priv)
	{
		WaitForSingleObject(priv->hThread, INFINITE);
		// 		CloseHandle(priv->hThread);
		// ɾ����Դ
		if(th->pPriv)
		{
			delete priv;
			th->pPriv = NULL;
		}
	}
	return 0;
}

void os_thread_msleep(int ms)
{
	Sleep(ms);
}

void os_thread_sleep(int s)
{
	Sleep(s * 1000);
}

unsigned long int os_thread_id()
{
	return GetCurrentThreadId();
}

#endif
